#include "tracker.h"
#include <sys/prctl.h>
#include <sys/thread_properties.h>
#include "ucontext.h"
#include "sys/ucontext.h"
#include "sstream"
#include "ctime"

/// 在官网上是能够查询到该信号在Linux下是注册的。https://cs.android.com/android/platform/superproject/main/+/main:external/musl/arch/arm/bits/signal.h;l=61?q=SIGUSR&ss=android&hl=zh-cn
/// 虽然不知道为什么，使用SIGUSR1的时候会导致接收不到信息，但是使用SIGUSR2的时候能正常接收到。因此注册SIGUSR2
/// 在 arm64-v8a架构中，采用SIGUSR2接收信息
#define REC_SIGN SIGUSR2

/// 游离的静态对象，需要对该对象的生命周期负责。
static pthread_t mainThread = 0;

void Tracker::trackerActionWithSignum(int signum, siginfo_t *info, void *invokeContext)
{
    if (signum == REC_SIGN)
    {
        /// then read thread frame, -----> arm64-v8a
        Logger::logInfo(TRACKER_TAG, "receive SIGUSR2");

        /// 在此获取 arm64-v8a 架构的线程堆栈信息
        auto *ucontext = (ucontext_t *)invokeContext;
        /// 一般情况，x29 为第30个寄存器，存放着帧指针
        /// 理论上，还需要获取一下pc指针，以至于可以通过pc指针地址、fp指针地址进行还原
        uint64_t fp = ucontext->uc_mcontext.regs[29];
        uint64_t lr = ucontext->uc_mcontext.regs[30];

        int deep = STACK_DEEP;
        int backline = 0;
        std::stringstream ss;
        ss << "---------------------------------------------------" << std::endl
           << "Architecture: ";
#if defined(__arm__) || defined(_M_ARM)
        ss << "ARM";
#elif defined(__aarch64__)
        ss << "ARM64";
#endif
        ss << " " << TRACKER_TAG << std::endl
           << "record time: " << std::time(nullptr) << std::endl
           << "isolate_instructions: " << std::hex << baseIsolateInstructions << ", "
           << "vm_instructions: " << std::hex << baseVmInstructions << std::endl;
        while (fp && lr && deep--)
        {
            if (*((uint64_t *)fp) < fp)
            {
                break;
            }

            /// 空指针判断
            if (!(fp + 8) || !(uint64_t *)fp)
            {
                break;
            }

            ss << transformFormat(backline, lr, baseIsolateInstructions)
               << std::endl;

            /// 更新指针
            lr = *((uint64_t *)(fp + 8));
            fp = *((uint64_t *)fp);
            backline++;
        }

        std::string sstemp;
        sstemp.append("save path: ").append(staceSavePath).append("write what?").append(ss.str());

        int saveSuccess = FileSaveUtil::saveStrFile(staceSavePath, ss.str());
        sstemp.append("save success: ").append(std::to_string(saveSuccess));
        Logger::logInfo(TRACKER_TAG, sstemp.c_str());

        ss.clear();
    }
}

void Tracker::registerSignalListener()
{
    printCurrentThreadInfo(TRACKER_TAG);
    /// 获取主线程对象
    mainThread = pthread_self();
    actionNew.sa_sigaction = trackerActionWithSignum;
    sigemptyset(&actionNew.sa_mask);
    /// 通过这个 sa_flags 可以获取到对应的信息，之后根据线程的上下文信息，获取对应的堆栈信息
    actionNew.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    if (sigaction(REC_SIGN, &actionNew, nullptr) == 0)
    {
        isRegister = 1;
    }
    else
    {
        isRegister = 0;
    }
}

void Tracker::setBaseIsolateInstructions(uint64_t isolateInstructions, uint64_t vmInstructions)
{
    baseIsolateInstructions = isolateInstructions;
    baseVmInstructions = vmInstructions;
}

void Tracker::unregisterSignalListener()
{
    if (isRegister)
    {
        sigaction(REC_SIGN, nullptr, &actionNew);
    }
    isRegister = 0;
    mainThread = 0;
}

void Tracker::track()
{
    printCurrentThreadInfo(TRACKER_TAG);
    if (mainThread)
    {
        pthread_kill(mainThread, REC_SIGN);
    }
}

Tracker::Tracker()
{
}

Tracker::~Tracker()
{
    mainThread = 0;
}